/**
* @file drv_dac.c
* @brief 对DAC进行配置，DMA搬运，TIM2为触发源
* @version 1.0 
* @author YeGuanyong
* @date 2022年4月22日
*/

#include "drv_dac.h"

static const dac_gpio gpio_list[DAC_CHANNEL_NUM] = 
{
	{DAC_PIN1, DAC_PORT1},
	{DAC_PIN2, DAC_PORT2},
};

static uint16_t sine12bit[POINTNUM] = {
	  2047, 2447, 2831, 3185, 3498, 3750, 3939, 4056, 4095, 4056,
	  3939, 3750, 3495, 3185, 2831, 2447, 2047, 1647, 1263, 909, 
	  599, 344, 155, 38, 0, 38, 155, 344, 599, 909, 1263, 1647};

/**
* @Description:DAC输出的GPIO配置.
* @param none.
* @return none.
*/
static void dac_gpio_cfg(void)
{
	GPIO_InitTypeDef gpio_init;
	const dac_gpio *pgpio = NULL;
	adc_gpio_clkopen();
	GPIO_StructInit(&gpio_init);

	gpio_init.GPIO_Speed = GPIO_Speed_50MHz; 
	gpio_init.GPIO_Mode = GPIO_Mode_AIN;
	for (pgpio = gpio_list; pgpio < &gpio_list[DAC_CHANNEL_NUM]; pgpio++)
	{
		gpio_init.GPIO_Pin = pgpio->pin;
		GPIO_Init(pgpio->gpio, &gpio_init);	
	}
}

/**
* @Description:DAC外设寄存器配置.
* @param dacx - DAC通道.
* @return none.
*/
static void dac_module_cfg(emDACCH_TypeDef dacx)
{
    DAC_InitTypeDef dac_init;
	
    DAC_StructInit(&dac_init);
	RCC_APB1PeriphClockCmd(RCC_APB1ENR_DAC, ENABLE);
#if TIM_TRIG
    dac_init.DAC_Trigger 		= DAC_Trigger_T2_TRIG;
#elif SW_TRIG
    dac_init.DAC_Trigger 		= DAC_Trigger_Software;
#endif
    dac_init.DAC_WaveGeneration	= DAC_WaveGeneration_None;
    dac_init.DAC_OutputBuffer 	= DAC_OutputBuffer_Enable;
    dac_init.DAC_LFSRUnmask_TriangleAmplitude 		= DAC_TriangleAmplitude_4095;
    DAC_Init(dacx, &dac_init);
#if SW_TRIG
    DAC->CR |= (DAC_CR_TEN1 | DAC_CR_TEN2);		/* 软件触发需要使能TENx位 */
#endif
}

/**
* @Description:DAC对应的DMA模块初始化.
* @param dac_adc_chx - 对应的DMA通道.
* @param regist - DAC输出数据寄存器地址.
* @return none.
*/
static void dac_dma_cfg(DMA_Channel_TypeDef *dac_adc_chx, uint32_t *regist)
{
    DMA_InitTypeDef dma_init;

    RCC_AHBPeriphClockCmd(RCC_AHBENR_DMA2, ENABLE);
    DMA_DeInit(dac_adc_chx);
    DMA_StructInit(&dma_init);
	
    dma_init.DMA_PeripheralBaseAddr = (uint32_t)regist;
    dma_init.DMA_MemoryBaseAddr		= (uint32_t)sine12bit;
    dma_init.DMA_DIR 				= DMA_DIR_PeripheralDST;
    dma_init.DMA_BufferSize 		= POINTNUM;
    dma_init.DMA_PeripheralInc 		= DMA_PeripheralInc_Disable;
    dma_init.DMA_MemoryInc 			= DMA_MemoryInc_Enable;
    dma_init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    dma_init.DMA_MemoryDataSize 	= DMA_MemoryDataSize_HalfWord;
    dma_init.DMA_Mode 				= DMA_Mode_Circular;
    dma_init.DMA_Priority 			= DMA_Priority_High;
    dma_init.DMA_M2M 				= DMA_M2M_Disable;
    dma_init.DMA_Auto_reload 		= DMA_Auto_Reload_Disable;
    DMA_Init(dac_adc_chx, &dma_init);
    DMA_Cmd(dac_adc_chx, ENABLE);
}

#if TIM_TRIG
/**
* @Description:DAC触发转换源TIM2的配置.
* @param none.
* @return none.
*/
static void dac_tim_config(void)
{
	TIM_TimeBaseInitTypeDef tim_init;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	
	tim_init.TIM_Period = 19;					/* 定时周期20 */
	tim_init.TIM_Prescaler = 1;					/* 2分频 */
	tim_init.TIM_ClockDivision = TIM_CKD_DIV1;	/* 时钟分频系数 */
	tim_init.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM2, &tim_init);

	TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);
	TIM_Cmd(TIM2, ENABLE);
}
#endif

/**
* @Description:初始化
* @param none.
* @return none.
*/
void module_dac_init(void)
{
	dac_gpio_cfg();
	dac_module_cfg(DAC_Channel_1);
	dac_module_cfg(DAC_Channel_2);
    DAC_Cmd(DAC_Channel_1, ENABLE);
    DAC_Cmd(DAC_Channel_2, ENABLE);
	
	DAC_DMACmd(DAC_Channel_1, ENABLE);
	DAC_DMACmd(DAC_Channel_2, ENABLE);
	
#if TIM_TRIG
	dac_tim_config();
#endif
	
	dac_dma_cfg(DMA2_Channel3, &(DAC->DHR12R1));
	dac_dma_cfg(DMA2_Channel4, &(DAC->DHR12R2));
}

